﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;
using TruyenTranhCrawler.Data;
using TruyenTranhCrawler.Helper;
using TruyenTranhCrawler.Utils;
using log4net;

namespace TruyenTranhCrawler
{
    public class Vitaku
    {
        private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        #region ctor
        private static readonly HtmlParser _parser = new HtmlParser();
        private static class Singleton
        {
            public static readonly Vitaku Instance = new Vitaku();
        }
        public static Vitaku Instance
        {
            get
            {
                return Singleton.Instance;
            }
        }
        #endregion

        #region Config

        private const string DomainLink = "http://vitaku.com";
        /// <summary>
        /// doc-truyen-tranh-online/page/{0}/
        /// </summary>
        const string UrlDataFormat = DomainLink + "/doc-truyen-tranh-online/page/{0}/";

        const string OpenTagDescipt = "<div class=\"ta_description";
        const string CloseTagDescript = "</div>";

        const string OpenChapItem = "<div style=\"width";
        const string CloseChapItem = "</div>";

        #endregion

        /// <summary>
        /// Xem tung trang, lay Book + chap luon, neu khong co truyen moi thi stop luon.
        /// </summary>
        /// <returns></returns>
        public void GetBooks()
        {
            int page = 0;
            while (true)
            {
                page++;
                int totalInPage = 0;
                var sources = Process.GetHtmlSources(string.Format(UrlDataFormat, page));
                if (sources.Length > 0)
                {
                    sources = _parser.Replace(sources, HtmlParser.Patterns.BREAK, " ");
                    var matchs = _parser.GetBetweenTag(sources, "article");
                    if (matchs.Count == 0) break;
                    foreach (Match m in matchs)
                    {
                        if (!_parser.Matched(m.Value, "post-")) continue;

                        try
                        {
                            var book = new Book
                            {
                                CrawlHost = "vitaku",
                                Source = "vitaku",
                                Types = "comic"//fixed
                            };
                            var titles = _parser.GetBetweenTag(m.Value, "h2");
                            if (titles.Count > 0)
                            {
                                var s = titles[0].Value;

                                var crawlUrl = _parser.GetProperty(s, "href")[0].Groups[4].Value.Trim();
                                book.CrawlUrl = HttpUtility.HtmlDecode(Process.FillAbsoluteLink(DomainLink, crawlUrl));
                                var cleartext = HttpUtility.HtmlDecode(_parser.RemoveAllTag(s));
                                var fullName = cleartext.Split('–')[0];
                                book.CrawlName = _parser.Replace(fullName, "(Đọc|online)", "").Trim();
                                book.FullName = book.CrawlName;
                            }
                            if (string.IsNullOrEmpty(book.CrawlUrl)) continue;

                            //kiem tra neu khong co chap moi thi stop luon, neu co thi get cac chap moi
                            if (Book.CanbeCrawl(ref book))
                            {
                                //get some info
                                //get image
                                if (string.IsNullOrEmpty(book.Image))
                                {
                                    var img = Process.GetFirstImg(m.Value);
                                    img = Process.FillAbsoluteLink(DomainLink, img);
                                    if (!_parser.Matched(img, Config.GoogleHostPattern))
                                    {
                                        //upload to picasa
                                        var sortname = string.IsNullOrEmpty(book.SortName) ? BaseObject.GetSortName(book.FullName) : book.SortName;
                                        var imginfos = ImageHelper.GetImage(img, sortname, Config.BookFolder);
                                        if (!string.IsNullOrEmpty(imginfos[0]))
                                        {
                                            img = imginfos[0];
                                        }
                                    }
                                    book.Image = img;
                                }
                                var newChap = GetNewChaps(book);
                                if (newChap == 0)
                                {
                                    break;
                                }
                                totalInPage++;    //logging
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(ex);
                        }
                    }
                }

                //Neu khong phai lan dau tien get data
                //chi kiem tra den trang 2 neu khong co new chap thi break luon
                if (!Config.VitakuFirstGetData && page >= 2 && totalInPage == 0)
                {
                    Logger.Info("no books update.");
                    break; //stop working
                }
            }
        }

        /// <summary>
        /// Lay tat ca thong tin con thieu cua Book + Get list new chap update. Return number of chap updated
        /// </summary>
        public int GetNewChaps(Book b)
        {
            int newcount = 0;
            var sources = Process.GetHtmlSources(b.CrawlUrl);
            if (sources.Length > 0)
            {
                sources = _parser.Replace(sources, HtmlParser.Patterns.BREAK, " ");
                try
                {
                    var isChanged = false;

                    if (string.IsNullOrEmpty(b.Description))
                    {
                        var blocks = _parser.GetContentInNode(sources, OpenTagDescipt, CloseTagDescript);
                        if (blocks.Count > 0)
                        {
                            var desc = _parser.RemoveTagOnly(blocks[0], new[] { "span", "div", "a", "script" });
                            b.Description = HttpUtility.HtmlDecode(desc);
                            isChanged = true;
                        }
                    }

                    if (b.ID == 0)
                    {
                        b.Save();
                    }
                    else if (isChanged)
                    {
                        b.Update();
                    }
                    var ccl = new CommonCrawler();

                    //get list chapter
                    var allExisted = Content.FindByBook(b.ID).Select(x => x.CrawlUrl).ToList();

                    var blocklistchap = _parser.GetContentInNode(sources, OpenChapItem, CloseChapItem);
                    if (blocklistchap.Count > 0)
                    {
                        var allChapFromSource = _parser.GetBetweenTag(blocklistchap[0], "a");
                        //loc qua 1 lan, bo qua cac link ko co noi dung
                        var realItems = (from Match item in allChapFromSource let clear = _parser.RemoveAllTag(item.Value).Trim() where clear.Length > 0 select item.Value).ToList();
                        int totalFromSource = realItems.Count;
                        if (totalFromSource > allExisted.Count)
                        {
                            var lastChapId = 0;
                            var idx = 1;
                            //(index =0 la chuong moi nhat)
                            while (idx <= totalFromSource)
                            {
                                var item = realItems[totalFromSource - idx];
                                var urls = _parser.GetProperty(item, "href");
                                if (urls.Count > 0)
                                {
                                    var chap = new Content { Book_ID = b.ID, Chapter = allExisted.Count + 1, SafeNameBook = b.SafeName };
                                    var crawlUrl = urls[0].Groups[4].Value.Trim();
                                    chap.CrawlUrl = Process.FillAbsoluteLink(DomainLink, crawlUrl);

                                    if (!allExisted.Contains(chap.CrawlUrl))
                                    {
                                        allExisted.Add(chap.CrawlUrl); //add into existed

                                        chap.Title = HttpUtility.HtmlDecode(_parser.RemoveAllTag(item).Trim());
                                        chap.Body = ccl.GetChapBody(chap.CrawlUrl);
                                        chap.Broken = chap.Body.Length == 0;
                                        chap.Save();
                                        lastChapId = chap.Content_ID;

                                        newcount++;
                                    }
                                }
                                
                                idx++;
                            }
                            if (lastChapId > 0)
                                Book.UpdateLastChap(b.ID, lastChapId, allExisted.Count);
                        }
                    }
                    if (newcount > 0)
                        Logger.Info(string.Format("New chap for book ID:{0}, sortname:{1}, finish: {2}, total chap:{3}", b.ID, b.SortName, b.Finish, newcount));
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                }
            }
            return newcount;
        }
    }
}

